// fountain.c++
// fountain class implementation file

#include <cassert>
#include <deque>

#include <iostream>

#include "map.h"
#include "object.h"
#include "fountain.h"

extern Map* map;

Fountain::Fountain() {
	assert(0);
}

Fountain::Fountain(const unsigned int x, const unsigned int y) : Object(x, y) {
	flowRate_ = 10;
	map->setTile(1, x, y, 1);
}

void Fountain::draw() {
	
}

void Fountain::activate() {
	
}

void Fountain::tick() {
	assert(x_ < map->getWidth());
	assert(y_ < map->getHeight());
	return;
	// create map of tiles that have been checked (initially none of them)
	bool** checked = new bool* [map->getWidth()];
	for (unsigned int x = 0; x < map->getWidth(); ++x) {
		checked[x] = new bool [map->getHeight()];
		for (unsigned int y = 0; y < map->getHeight(); ++y) {
			checked[x][y] = 0;
		}
	}
	// create list of tiles to submerge
	std::deque<unsigned int> nextX;
	std::deque<unsigned int> nextY;
	// recursively flood tiles to fill list of tiles to submerge
	floodTile(checked, nextX, nextY, x_, y_);
	// submerge each tile in list, updating list appropriately
	for (unsigned int i = 0; (i < flowRate_) && (i < nextX.size())
		                                     && (i < nextY.size()); ++i) {
		// submerge next tile
		map->setTile(1, nextX.front(), nextY.front(), 1);
		// remove tile from list
		nextX.pop_front();
		nextY.pop_front();
		// water has changed; update list accordingly
		floodTile(checked, nextX, nextY, nextX.front(), nextY.front());
	}
}

ObjectType Fountain::getObjectType() {
	return FOUNTAIN;
}

void Fountain::floodTile(bool** checked, std::deque<unsigned int>& nextX,
                         std::deque<unsigned int>& nextY, const unsigned int x,
                         const unsigned int y) {
	assert(x < map->getWidth());
	assert(y < map->getHeight());
	// set checked bool
	checked[x][y] = 1;
	// if target tile is water
	if (map->getTile(1, x, y)) {
		// flood all adjacent tiles
		// if there is a tile to the north
		if ((y > 0) && !checked[x][y - 1]) {
			// flood it
			floodTile(checked, nextX, nextY, x, y - 1);
		}
		// if there is a tile to the east
		if ((x < (map->getWidth() - 1)) && !checked[x + 1][y]) {
			// flood it
			floodTile(checked, nextX, nextY, x + 1, y);
		}
		// if there is a tile to the south
		if ((y < (map->getHeight() - 1)) && !checked[x][y + 1]) {
			// flood it
			floodTile(checked, nextX, nextY, x, y + 1);
		}
		// if there is a tile to the west
		if ((x > 0) && !checked[x - 1][y]) {
			// flood it
			floodTile(checked, nextX, nextY, x - 1, y);
		}
	// if target tile is not water
	} else {
		// insert tile's coordinates into list of tiles to submerge
		for (unsigned int i = 0; i < flowRate_; ++i) {
			// if we have reached the end of the current to-flood list
			if ((i == nextX.size()) || (i == nextY.size())) {
				// add tile to end of list
				nextX.push_back(x);
				nextY.push_back(y);
				// we are done
				return;
			// otherwise, if current tile is lower than tile i
			} else if (map->getTile(0, x, y) < map->getTile(0, nextX.at(i),
			                                                nextY.at(i))) {
				// insert tile into list
				nextX.insert(nextX.begin() + i, x);
				nextY.insert(nextY.begin() + i, y);
				// remove tile that was pushed off the end of the list
				nextX.pop_back();
				nextY.pop_back();
				// we are done
				return;
			}
		}
	}
}

unsigned int Fountain::getFlowRate() {
	return flowRate_;
}

void Fountain::setFlowRate(const unsigned int flowRate) {
	flowRate_ = flowRate;
}

